package AlgebraLinear.Matriz;

import java.text.DecimalFormat;

public class FuncoesMatriz {

        private static DecimalFormat aprox = new DecimalFormat("0.0####");

	public static String imprimirMatriz(double[][] matriz){
		String saida = "";
		for (int i = 0; i < matriz.length; i++) {
			for (int j = 0; j < matriz[i].length; j++) {
				saida += aprox.format(matriz[i][j])+"\t";
			}
			saida +="\n";
		}
		return saida;
	}
	
	//Verifica se é uma matriz valida
	public static void verificaMatriz(double[][] matriz){
		int colunaLinha = 0;
		for (int i = 0; i < matriz.length; i++) {
			if( colunaLinha != matriz[i].length && colunaLinha !=0){
				throw new IllegalArgumentException
                                        ("A sua Matriz possui um número"+
                                        "inrregulares de colunas");
			}
		}
	}
	
	public static void verificaMatrizQuad(double[][] matriz) {
		FuncoesMatriz.imprimirMatriz(matriz);
		//Verifico se cada linha possui
                //um numero de colunas igual à linhas
		for (int i = 0; i < matriz.length; i++) {
			if (matriz.length != matriz[i].length) {
				throw new IllegalArgumentException
                                        ("A matriz informada não é quadrada");
			}
		}
	}

	public static double[][] preencherIdentidade(int ordem){
		double[][] identidade = new double[ordem][ordem];
		for(int i = 0; i < identidade.length; i++){
			identidade[i][i] = 1;
		}
		return identidade;
	}
	
	//Operacoes com Determinantes
	public static void verificaDeterminante(double[][] matriz){
		if(calculaDeterminante(matriz) == 0.0){
			throw new IllegalArgumentException
                            ("A determinante é 0, portanto não possui inversa");
		}
	}
	
	private static double calculaDeterminante(double[][] matriz){
		
		double determinante = 1;
		for (int i = 0; i < matriz.length; i++) {
			determinante *= matriz[i][i];
		}
		return determinante;
	}
	
	public static String Determinante(double[][] matriz){
		
		double[][] matrizTriangularSuperior =
                        obterMatrizTriSuperior(matriz);
		return aprox.format(
                        calculaDeterminante(matrizTriangularSuperior)
                        );
	}
	//Acessório para o calculo de Determinante
	private static double[][] obterMatrizTriSuperior(double[][] arg0){
		
		double[][] matriz = preencherNovaMatriz(arg0);
		
		for(int etapa = 0; etapa < (matriz.length-1); etapa++){
			for(int i = etapa+1; i< matriz.length; i++){
				double mult = -1*(matriz[i][etapa]/matriz[etapa][etapa]);
				matriz[i][etapa] = 0;
			//Atualizo os outros elementos da matriz original
				for(int j = etapa+1; j < matriz[i].length; j++){
					matriz[i][j] = matriz[i][j]+
                                                (mult * matriz[etapa][j]);
				}
			}
		}
		return matriz;
	}
	
	//Metodo para preencher uma matriz com os valores de outra
	public static double[][] preencherNovaMatriz(double[][] matriz){
		double[][] novaMatriz =
                        new double[matriz.length][matriz[0].length];
		
		for (int i = 0; i < novaMatriz.length; i++) {
			for (int j = 0; j < novaMatriz[i].length; j++) {
				novaMatriz[i][j] = matriz[i][j];
			}
		}
		return novaMatriz;
	}
}
